package bubblesn;
import java.util.ArrayList;



/**
 * Class to represent normal bubble sorting network 
 * @author Rafalmag
 */
public class Bubble extends SortingNetwork {

	/**
	 * Constructor
	 * @param inLines describes size of input
	 * @throws Exception when inLines<2
	 */
	public Bubble(int inLines) throws Exception {
		super(inLines);
	}

	/* (non-javadoc)
	 * Makes all possible normal transitions and adds their lengths to pathlengths
	 */
	@Override
	public void doAllTransitions(final int threads){
		if(threads==1){
			for(int i=0; i<inputLines; i++){
				transition(Gate.input, new Coordinate(0, i, Direction.right), 0);
			}
		}else{
			ArrayList<Thread> threadList = new ArrayList<Thread>();
			for(int t=0; t<threads; t++){
				final int tt=t;
				Thread tmp= new Thread(new Runnable() {
		            public void run() {
		            	for(int i=0; i<inputLines; i++){
		            		if(i%threads==tt){
		            			transition(Gate.input, new Coordinate(0, i, Direction.right), 0);
		            		}
		            	}
		            }
		        });
				tmp.start();
				threadList.add(tmp);				
			}
			
			// waits for threads to end
			//System.out.println("Joining");
			for (Thread t : threadList){
				try {
					t.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}	
		}
	}
	
	/**
	 * Makes single transition in normal bubble sorting network
	 * @param from - type of gate, which we come from
	 * @param to - end coordinate
	 * @param gates - how many gates have been visited
	 */
	@Override
	public void transition(Gate from, Coordinate to, int gates){
		Coordinate now= new Coordinate(to);
		Gate nowFrom=this.network[now.y][now.x];
		switch(nowFrom){
			//case input:
				// do the same as path
			case path:
				// goes right not through a gate
				to = now.go(Direction.right);
				transition(nowFrom, to, gates);
				break;
			case and:
				if(now.dir==Direction.down){
					// goes right through a gate
					to = now.go(Direction.right);
					transition(nowFrom, to, gates+1);
				}else{
					// goes up not through a gate					
					to = now.go(Direction.up);
					transition(nowFrom, to, gates);
					
					// goes right through a gate
					to = now.go(Direction.right);
					transition(nowFrom, to, gates+1);
				}
				break;
			case or:
				if(now.dir==Direction.up){
					// goes right through a gate
					to = now.go(Direction.right);
					transition(nowFrom, to, gates+1);
				}else{
					// goes down not through a gate					
					to = now.go(Direction.down);
					transition(nowFrom, to, gates);
					
					// goes right through a gate
					to = now.go(Direction.right);
					transition(nowFrom, to, gates+1);
				}
				break;
			case output:
				// it is the end of path
				pathlengths.addGatesNumToOutput(now.y, gates);
				break;
			default:
				System.out.println("Error parsing Gate from");
		}
	}
}
